using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Collections.Generic;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

using Peradigm.Framework.Domain.Collections;
using Peradigm.Framework.Domain.Collections.Generic;
using Peradigm.Framework.Domain.Security;
using Peradigm.Framework.Persistence;
using Peradigm.Framework.UI.Web;

using Liberty.Application.ApplicationManagement;
using Liberty.Application.ServiceMemberManagement;
using Liberty.Application.GrantManagement;
using Liberty.Application.Security;

using Liberty.Domain;
using Liberty.Domain.ApplicationManagement;
using Liberty.Domain.GrantManagement;
using Liberty.Domain.CaseManagement;
using Liberty.Domain.ServiceMemberManagement;

namespace Liberty.UI.GrantManagement.Controls
{
    public partial class GrantListView : AbstractLibertyControl
    {
        #region Constants
        private const string
            SESSION_MODEL = "GrantListView.Model",
            SORT_ASCENDING = "Ascending",
            SORT_DESCENDING = "Descending",
            SORT_ORDER = "SortOrder",
            DEFAULT_SORT_ORDER = "Case.ServiceMember.LastName",
            CMD_APPROVE_ID = "cmdApprove",
            CMD_DISPERSE_ID = "cmdDisperse",
            KEY_GRANT = "Grant",
            KEY_USER = "CurrentUser",

            COMMAND_NAME_SERVICE_MAN_SELECTED = "ServiceManSelected",
            COMMAND_NAME_APPROVE = "Approve",
            COMMAND_NAME_DISPERSE = "Disperse",
            COMMAND_GRANT_AMOUNT_SELECTED = "GrantAmountSelected";

        #endregion

        #region Event Handlers
        protected void Page_Load( object sender, EventArgs e )
        {
            this.BuildGridViewCommandHandlers();
            if (this.SortedListFrom((List<Grant>)this.Model).Count > 0)
            {
                this.divNumRows.Visible = true;
            }
            else
            {
                this.divNumRows.Visible = false;
            }

            if (!this.IsPostBack)
            {
                if (Profile.NumRows == 0) Profile.NumRows = 10;
                this.ddlNumRows.Items.FindByValue(Profile.NumRows.ToString()).Selected = true;
            }



        }

        protected void gvGrantList_RowCommand( object sender, GridViewCommandEventArgs e )
        {
            if ( this.GridViewCommandHandlers.ContainsKey( e.CommandName ) )
            {
                GridViewCommandHandler handler = this.GridViewCommandHandlers[e.CommandName];
                handler( e );
            }
        }

       
        protected void ddlNumRows_SelectedIndexChanged(object sender, EventArgs e)
        {
            Profile.NumRows = Convert.ToInt32(ddlNumRows.SelectedValue);
        }

      
        protected void gvGrantList_RowDataBound( object sender, GridViewRowEventArgs e )
        {
            if ( e.Row.RowType == DataControlRowType.DataRow )
            {
                Grant grant = (Grant)e.Row.DataItem;
                bool canApprove = this.CanUserApprove( grant );
                bool canDisperse = this.CanUserDisperse( grant );

                Button cmdApprove = (Button)e.Row.FindControl( CMD_APPROVE_ID );
                Button cmdDisperse = (Button)e.Row.FindControl( CMD_DISPERSE_ID );
                cmdApprove.Visible = false;
                cmdDisperse.Visible = false;
                if ( canApprove )
                {
                    cmdApprove.Visible = true;
                    cmdDisperse.Visible = false;
                }
                else if ( canDisperse )
                {
                    cmdDisperse.Visible = true;
                    cmdApprove.Visible = false;
                }
            }
        }

        protected void gvGrantList_Sorting(object sender, GridViewSortEventArgs e)
        {          

            this.SetSortOrderUsing(e.SortExpression);
        }

        protected void gvGrantList_PageIndexChanging( object sender, GridViewPageEventArgs e )
        {
            gvGrantList.DataSource = this.SortedListFrom( (List<Grant>)this.Model );
            gvGrantList.PageIndex = e.NewPageIndex;
            gvGrantList.DataBind();

        }
        #endregion

        #region Methods

        protected string DisplayFacility(Case aCase)
        {
            string facility = String.Empty;
            if( aCase.CurrentVisit.Facility != null )
            {
                facility = aCase.CurrentVisit.Facility.Name;
            }
            return facility;
        }

        public override void UpdateView()
        {
           
            gvGrantList.PageSize = 25;

            gvGrantList.DataSource = this.SortedListFrom( (List<Grant>)this.Model );
            gvGrantList.DataBind();
        }

        public void InitializeView()
        {
        }
        #endregion

        #region Properties
        public override object Model
        {
            get
            {
                return Session[SESSION_MODEL];
            }
            set
            {
                Session[SESSION_MODEL] = value;
            }
        }

        /// <summary>
        /// Delegate to register callbacks of the type ServiceMemberSelected.
        /// </summary>
        public event ServiceMemberSelectedEventHandler ServiceMemberSelectedListeners
        {
            add
            {
                i_ServiceMemberSelectedEvent += value;
            }
            remove
            {
                i_ServiceMemberSelectedEvent -= value;
            }
        }

        /// <summary>
        /// Delegate to register callbacks of the type GrantSelected.
        /// </summary>
        public event GrantSelectedEventHandler GrantSelectedListeners
        {
            add
            {
                i_GrantSelectedEvent += value;
            }
            remove
            {
                i_GrantSelectedEvent -= value;
            }
        }

        /// <summary>
        /// Delegate to register callbacks of the type RecipientSelected.
        /// </summary>
        public event RecipientSelectedEventHandler RecipientSelectedListeners
        {
            add
            {
                i_RecipientSelectedEvent += value;
            }
            remove
            {
                i_RecipientSelectedEvent -= value;
            }
        }
        #endregion

        #region Private Methods
        private void BuildGridViewCommandHandlers()
        {
            this.GridViewCommandHandlers = new Dictionary<string, GridViewCommandHandler>();
            this.GridViewCommandHandlers.Add( COMMAND_NAME_SERVICE_MAN_SELECTED, new GridViewCommandHandler( this.ServiceMemberSelectedHandler ) );
            this.GridViewCommandHandlers.Add(COMMAND_GRANT_AMOUNT_SELECTED, new GridViewCommandHandler(this.GrantAmountSelectedHandler));
            this.GridViewCommandHandlers.Add( COMMAND_NAME_APPROVE, new GridViewCommandHandler( this.GrantApprovedHandler ) );
            this.GridViewCommandHandlers.Add( COMMAND_NAME_DISPERSE,  new GridViewCommandHandler( this.GrantDispersedHandler ) );
        }

        private void ServiceMemberSelectedHandler( GridViewCommandEventArgs e )
        {
            ServiceMember servicemember = this.ServiceMemberWith( Convert.ToInt64( e.CommandArgument ) );
            this.RaiseServiceMemberSelectedEvent( servicemember );
        }

        private void GrantAmountSelectedHandler(GridViewCommandEventArgs e)
        {
            Grant SelectGrant = this.GrantWith(Convert.ToInt64(e.CommandArgument));
            this.RaiseGrantAmountSelectedEvent(SelectGrant);
        }

        private void GrantApprovedHandler( GridViewCommandEventArgs e )
        {
            Grant grant = this.GrantWith( Convert.ToInt64( e.CommandArgument ) );
            this.ApproveGrant( grant );
        }

        private void GrantDispersedHandler( GridViewCommandEventArgs e )
        {
            Grant grant = this.GrantWith( Convert.ToInt64( e.CommandArgument ) );
            this.DisperseGrant( grant );
        }

        private void ApproveGrant( Grant grant )
        {
            grant.ApproveBy( this.User );
            new GrantController().SaveGrant( grant );
        }

        private void DisperseGrant( Grant grant )
        {
            grant.DisperseBy( this.User );
            new GrantController().SaveGrant( grant );
        }

        private bool CanUserApprove( Grant grant )
        {
            Dictionary<string, object> context = new Dictionary<string, object>();
            context.Add( ViewGrantPrivilege.KEY_USER, this.User );
            context.Add( ViewGrantPrivilege.KEY_GRANT, grant );
            return this.User.HasPermissionTo( Privilege.Actions.Approve, context );
        }

        private bool CanUserDisperse( Grant grant )
        {
            Dictionary<string, object> context = new Dictionary<string, object>();
            context.Add( ViewGrantPrivilege.KEY_USER, this.User );
            context.Add( ViewGrantPrivilege.KEY_GRANT, grant );
            context.Add( DisperseGrantPrivilege.PRIVILEGE_DISPERSE_GRANT, DisperseGrantPrivilege.PRIVILEGE_DISPERSE_GRANT );
            return this.User.HasPermissionTo( Privilege.Actions.Approve, context );
        }

        private ServiceMember ServiceMemberWith( long id )
        {
            ServiceMemberController controller = new ServiceMemberController();
            return controller.ServiceMemberWith( id );
        }

        private Grant GrantWith( long oid )
        {
            List<Grant> grants = (List<Grant>)this.Model;
            return grants.Find( grant => grant.Oid == oid );
        }

        private Applicant RecipientWith( long id )
        {
            ApplicantController controller = new ApplicantController();
            return controller.ApplicantWith(id);

        }

        private void RaiseServiceMemberSelectedEvent( ServiceMember serviceMember )
        {
            if( this.ServiceMemberSelectedEvent != null )
            {
                this.ServiceMemberSelectedEvent( serviceMember );
            }
        }

        private void RaiseGrantAmountSelectedEvent(Grant selectedGrant)
        {
            if (this.GrantSelectedEvent!= null)
            {
                this.GrantSelectedEvent(selectedGrant);
            }
        }

        private void RaiseRecipientMemberSelectedEvent( Applicant recipient )
        {
            if( this.RecipientSelectedEvent != null )
            {
                this.RecipientSelectedEvent( recipient );
            }
        }
      

        private List<Grant> SortedListFrom( List<Grant> grants )
        {
            grants.Sort( new Sorter<Grant>( this.SortDirection, this.SortExpression ) );
            return grants;
        }

        private void SetSortOrderUsing( string newSortExpression )
        {
            if( newSortExpression != String.Empty )
            {
                if( newSortExpression == this.SortExpression )
                {
                    this.SortDirection = this.SortDirection == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending;
                }
                else
                {
                    this.SortDirection = SortOrder.Ascending;
                }
                this.SortExpression = newSortExpression;
            }
        }

        private SortOrder SortDirection
        {
            get
            {
                if (this.ViewState[SORT_ORDER] == null)
                {
                    this.ViewState[SORT_ORDER] = SORT_ASCENDING;
                }
                string sortDirection = this.ViewState[SORT_ORDER].ToString();
                return sortDirection == SORT_ASCENDING ? SortOrder.Ascending : SortOrder.Descending;            

            }
            set
            {
                this.ViewState[SORT_ORDER] = value == SortOrder.Ascending ? SORT_ASCENDING : SORT_DESCENDING;
            }
        }

        private string SortExpression
        {
            get
            {
                if( this.ViewState["SortExpression"] == null )
                {
                    this.ViewState["SortExpression"] = DEFAULT_SORT_ORDER;
                }
                return this.ViewState["SortExpression"].ToString();
            }
            set
            {
                this.ViewState["SortExpression"] = value;
            }
        }
        #endregion

        #region Private Properties
        private ServiceMemberSelectedEventHandler ServiceMemberSelectedEvent
        {
            get
            {
                return i_ServiceMemberSelectedEvent;
            }
        }
        
        private GrantSelectedEventHandler GrantSelectedEvent
        {
            get
            {
                return i_GrantSelectedEvent;
            }
        }

        private RecipientSelectedEventHandler RecipientSelectedEvent
        {
            get
            {
                return i_RecipientSelectedEvent;
            }
        }
        private Dictionary<string, GridViewCommandHandler> GridViewCommandHandlers
        {
            get
            {
                return i_GridViewCommandHandlers;
            }
            set
            {
                i_GridViewCommandHandlers = value;
            }
        }
        #endregion

        #region Data Elements
        private ServiceMemberSelectedEventHandler i_ServiceMemberSelectedEvent;
        private GrantSelectedEventHandler i_GrantSelectedEvent;
        private RecipientSelectedEventHandler i_RecipientSelectedEvent;
        private delegate void GridViewCommandHandler( GridViewCommandEventArgs e );
        private Dictionary<string, GridViewCommandHandler> i_GridViewCommandHandlers;
        #endregion

    }
}
